﻿using Newtonsoft.Json;
using System.Diagnostics;
using VisionDesigner;
using VisionDesigner.EdgePairFlawInsp;
using VM.Common.Enums;
using VM.Common.Helper;
using VM.Dialogs.Views;
using VM.Start.Common.Hik;
using VM.Start.Controls;

namespace Plugin.Defect
{

    #region enum

    public enum eSelectImageCommand
    {
        LocalImage,
        OtherImage
    }

    #endregion

    [JsonObject(MemberSerialization.OptOut)]
    public class DefectEditViewModel : NotifyPropertyBase
    {
        #region  属性
        [Newtonsoft.Json.JsonIgnore]
        public CMvdImage LocalImage;
        public uint Width;
        public uint Height;
        public MVD_PIXEL_FORMAT PIXEL_FORMAT = MVD_PIXEL_FORMAT.MVD_PIXEL_NULL;
        public MVD_IMAGE_DATA_INFO ImageData = null;
        [Newtonsoft.Json.JsonIgnore]
        private CMvdImage _TrainImage;
        [Newtonsoft.Json.JsonIgnore]
        public CMvdImage TrainImage
        {
            get
            {
                if ((_TrainImage == null || _TrainImage.IsEmpty) &&
                    ImageData != null && ImageData.stDataChannel[0].arrDataBytes != null &&
                    Width != 0 && Height != 0 && PIXEL_FORMAT != MVD_PIXEL_FORMAT.MVD_PIXEL_NULL)
                {
                    _TrainImage = new CMvdImage();
                    _TrainImage.InitImage(Width, Height, PIXEL_FORMAT, ImageData);
                }
                return _TrainImage;
            }
            set
            {
                _TrainImage = value;
                if (_TrainImage != null && !_TrainImage.IsEmpty)
                {
                    Width = _TrainImage.Width;
                    Height = _TrainImage.Height;
                    PIXEL_FORMAT = _TrainImage.PixelFormat;
                    ImageData = _TrainImage.GetImageData();
                }
                LearnMatch.Image = value;
            }
        }
        #region 训练结果图像
        public uint rWidth;
        public uint rHeight;
        public MVD_PIXEL_FORMAT rPIXEL_FORMAT = MVD_PIXEL_FORMAT.MVD_PIXEL_NULL;
        public MVD_IMAGE_DATA_INFO rImageData = null;
        [Newtonsoft.Json.JsonIgnore]
        private CMvdImage _rTrainImage;
        [Newtonsoft.Json.JsonIgnore]
        private CMvdImage rTrainImage
        {
            get
            {
                if ((_rTrainImage == null || _rTrainImage.IsEmpty) &&
                    rImageData != null && rImageData.stDataChannel[0].arrDataBytes != null &&
                    rWidth != 0 && rHeight != 0 && rPIXEL_FORMAT != MVD_PIXEL_FORMAT.MVD_PIXEL_NULL)
                {
                    _rTrainImage = new CMvdImage();
                    _rTrainImage.InitImage(rWidth, rHeight, rPIXEL_FORMAT, rImageData);
                }
                return _rTrainImage;
            }
            set
            {
                _rTrainImage = value;
                if (_rTrainImage != null && !_rTrainImage.IsEmpty)
                {
                    rWidth = _rTrainImage.Width;
                    rHeight = _rTrainImage.Height;
                    rPIXEL_FORMAT = _rTrainImage.PixelFormat;
                    rImageData = _rTrainImage.GetImageData();
                }
                TemplateWindow.Image = value;
            }
        }
        #endregion
        [Newtonsoft.Json.JsonIgnore]
        public TemplateModel m_TemplateModel;
        private List<CMvdPolylineSegmentF> _UIPolylineSegmentList = new List<CMvdPolylineSegmentF>();

        /// <summary>
        /// UI界面绘制的卡尺框
        /// </summary>
        private List<CMvdRectangleF> _UIResPatternCaliperList = new List<CMvdRectangleF>();

        /// 是否需要重新计算掩膜图像
        /// </summary>
        public bool m_bNeedUpdateMaskImg = false;
        /// <summary>
        /// UI界面绘制的边缘点
        /// </summary>
        private List<CMvdPointSetF> _UIResPatternEdgeList = new List<CMvdPointSetF>();
        [Newtonsoft.Json.JsonIgnore]
        public DefectViewModel matchingViewModel;
        [Newtonsoft.Json.JsonIgnore]
        public DefectEditView view;
        [Newtonsoft.Json.JsonIgnore]
        public CMvdImage OutImage;

        private Stopwatch _StopWatch = new Stopwatch();


        public CEdgePairFlawPattern _edgePairFlawPattern;
        // 定义 HPFeaturePattern 属性
        [Newtonsoft.Json.JsonIgnore]
        public CEdgePairFlawPattern EdgePairFlawPattern
        {
            get
            {
                if (_edgePairFlawPattern != null && _edgePairFlawPattern.Result == null
                    )
                {

                    _edgePairFlawPattern.InputImage = TrainImage;
                }

                return _edgePairFlawPattern;
            }
            set
            {
                if (_edgePairFlawPattern != value)
                {
                    _edgePairFlawPattern = value;
                    if (_edgePairFlawPattern.InputImage != null && !_edgePairFlawPattern.InputImage.IsEmpty)
                    {
                        LearnMatch.Image = _edgePairFlawPattern.InputImage;
                    }
                    if (_edgePairFlawPattern != null && _edgePairFlawPattern.Result != null)
                    {

                        DisplayTrainedImageAndOutline(TemplateWindow);
                    }
                }
            }
        }

        [Newtonsoft.Json.JsonIgnore]
        private List<CMvdPointSetF> _PatternOutlineList = new List<CMvdPointSetF>();    // 模型轮廓点集

        #endregion
        #region  数据接口

        [Newtonsoft.Json.JsonIgnore]
        public VMDisplayControl _LearnMatch;
        [Newtonsoft.Json.JsonIgnore]
        public VMDisplayControl LearnMatch
        {
            get
            {
                if (_LearnMatch == null)
                {
                    _LearnMatch = new VMDisplayControl();
                    _LearnMatch.MVDRender.MVDShapeChangedEvent += MVDRender_MVDShapeChangedEvent;

                }
                return _LearnMatch;
            }
        }

        [Newtonsoft.Json.JsonIgnore]
        public VMDisplayControl _TemplateWindow;
        [Newtonsoft.Json.JsonIgnore]
        public VMDisplayControl TemplateWindow
        {
            get
            {
                if (_TemplateWindow == null)
                {
                    _TemplateWindow = new VMDisplayControl();
                }
                return _TemplateWindow;
            }
        }
        /// <summary>
        /// 参数
        /// </summary>
        public TemplateParamModel Param { get; set; } = new TemplateParamModel();
        /// <summary>
        /// 指定ROI
        /// </summary>
        private ROITypeEnum _EditROIMode = ROITypeEnum.全图;
        public ROITypeEnum EditROIMode
        {
            get { return _EditROIMode; }
            set
            {
                Set(ref _EditROIMode, value, new Action(() =>
                {
                    switch (_EditROIMode)
                    {
                        case ROITypeEnum.全图:
                            LearnMatch.ROIType = ROITypeEnum.全图;
                            break;
                        case ROITypeEnum.矩形:
                            LearnMatch.ROIType = ROITypeEnum.矩形;
                            break;
                        case ROITypeEnum.圆:
                            LearnMatch.ROIType = ROITypeEnum.圆;
                            break;
                        default:
                            break;
                    }
                }));
            }
        }
        #endregion
        #region  指令
        [Newtonsoft.Json.JsonIgnore]
        private CommandBase _SelectImageCommand;
        [Newtonsoft.Json.JsonIgnore]
        public CommandBase SelectImageCommand
        {
            get
            {
                if (_SelectImageCommand == null)
                {
                    _SelectImageCommand = new CommandBase(
                        (obj) =>
                        {
                            try
                            {


                                eSelectImageCommand par = (eSelectImageCommand)obj;
                                switch (par)
                                {
                                    case eSelectImageCommand.LocalImage:
                                        TrainImage = LocalImage;
                                        m_bNeedUpdateMaskImg = true;
                                        _UIPolylineSegmentList.Clear();
                                        break;
                                    case eSelectImageCommand.OtherImage:
                                        Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
                                        dlg.Filter = "所有图像文件 | *.bmp; *.pcx; *.png; *.jpg; *.gif;*.tif; *.ico; *.dxf; *.cgm; *.cdr; *.wmf; *.eps; *.emf";
                                        if (dlg.ShowDialog() == true)
                                        {
                                            RImage rImage = new RImage();
                                            rImage.InitImage(dlg.FileName, VisionDesigner.MVD_PIXEL_FORMAT.MVD_PIXEL_MONO_08);
                                            TrainImage = rImage;
                                        }
                                        m_bNeedUpdateMaskImg = true;
                                        _UIPolylineSegmentList.Clear();
                                        break;
                                    default:
                                        throw new ArgumentOutOfRangeException();
                                }
                            }
                            catch (Exception ex)
                            {

                            }
                        }
                    );
                }
                return _SelectImageCommand;
            }
        }

        [Newtonsoft.Json.JsonIgnore]
        private CommandBase _learnCommand;
        [Newtonsoft.Json.JsonIgnore]
        public CommandBase LearnCommand
        {
            get
            {
                if (_learnCommand == null)
                {
                    _learnCommand = new CommandBase((obj) =>
                    {
                        CreateModel();
                    });
                }
                return _learnCommand;
            }
        }

        [Newtonsoft.Json.JsonIgnore]
        private CommandBase _ConfirmCommand;
        [Newtonsoft.Json.JsonIgnore]
        public CommandBase ConfirmCommand
        {
            get
            {
                if (_ConfirmCommand == null)
                {
                    _ConfirmCommand = new CommandBase((obj) =>
                    {
                        if (view != null)
                        {
                            CreateModel();
                            if (m_TemplateModel == null && EdgePairFlawPattern.Result != null && EdgePairFlawPattern != null)
                            {
                                m_TemplateModel = new TemplateModel();
                                string baseName = "新建模板";
                                int index = 1;
                                string newName;

                                // 循环检查名称是否已存在
                                do
                                {
                                    newName = $"{baseName}{index}";
                                    index++;
                                } while (matchingViewModel.TemplateList.Any(template => template.Name == newName));
                                m_TemplateModel.Name = newName;
                                m_TemplateModel.Index = matchingViewModel.TemplateList.Count;
                                matchingViewModel.TemplateList.Add(m_TemplateModel);
                                m_TemplateModel.Data = this;
                                matchingViewModel.SelectedTemplate = m_TemplateModel;
                            }

                            view.Close();
                        }
                    });
                }
                return _ConfirmCommand;
            }
        }

        #endregion
        #region  方法
        /// <summary>
        public void Loaded()
        {
            if (TrainImage != null && !TrainImage.IsEmpty)
            {
                LearnMatch.Image = TrainImage;
            }
            if (rTrainImage != null && !rTrainImage.IsEmpty)
            {
                TemplateWindow.Image = rTrainImage;
                TemplateWindow.MVDRender.Display(MVDRenderActivex.MVD_REFRESH_MODE.Sync);
                TemplateWindow.DrawPointSetFList(_PatternOutlineList);
            }
        }

        public void CreateModel()
        {

            try
            {
                if ((null == EdgePairFlawPattern) || (null == LearnMatch.Image))
                {
                    throw new MvdException(MVD_MODULE_TYPE.MVD_MODUL_APP, MVD_ERROR_CODE.MVD_E_CALLORDER);
                }
                EdgePairFlawPattern.InputImage = LearnMatch.Image;
                EdgePairFlawPattern.BasicParam.TrajList = _UIPolylineSegmentList;

                UpdatePatCreateParas(EdgePairFlawPattern);
                _StopWatch.Restart();
                EdgePairFlawPattern.Train();
                _StopWatch.Stop();
                var result = EdgePairFlawPattern.Result;

                if (null == result)
                {
                    MessageView.Ins.MessageBoxShow("Pattern result is null! \r\n", eMsgType.Warn);
                    return;
                }
                DrawCaliper(result.CaliperBoxList);

                // 渲染轮廓点
                DrawEdge(result.Edge0PointList);
                DrawEdge(result.Edge1PointList);
                //var patternData = EdgePairFlawPattern.Result.Data;

                //Param.ParamInt["卡尺间距"] = patternData.ModCaliperDistCourse;
                //Param.ParamInt["卡尺高度"] = Convert.ToInt32(patternData.Fine);
                //Param.ParamInt["卡尺宽度"] = patternData.ModCaliperWidth;
                //Param.ParamInt["理想宽度"] = patternData.ModEdgeStrength;
                //Param.ParamInt["边缘强度"] = patternData.LowThreshold;

                TemplateWindow.Copy(LearnMatch);
                TemplateWindow.MVDRender.Show();
                //   DisplayTrainedImageAndOutline(TemplateWindow);

            }
            catch (Exception ex)
            {

            }
        }

        public void UpdatePatCreateParas(CEdgePairFlawPattern cedgePairFlawPattern)
        {
            cedgePairFlawPattern.SetRunParam("ModEdgePairFindMode", Param.ParamMap[Param.FindModeMode]);

            cedgePairFlawPattern.SetRunParam("ModEdgePairEdge0Polarity", Param.ParamMap[Param.Edge0Polarity]);
            cedgePairFlawPattern.SetRunParam("ModEdgePairEdge1Polarity", Param.ParamMap[Param.Edge1Polarity]);
            cedgePairFlawPattern.SetRunParam("ModCaliperWidth", Param.CaliperWidth.ToString());
            cedgePairFlawPattern.SetRunParam("ModCaliperHeight", Param.CaliperHeight.ToString());
            cedgePairFlawPattern.SetRunParam("ModCaliperDistCourse", Param.DistCourse.ToString());
            cedgePairFlawPattern.SetRunParam("ModEdgeStrength", Param.EdgeStrength.ToString());


        }
        /// <summary>
        /// 展示模型图像和轮廓
        /// </summary>
        public void DisplayTrainedImageAndOutline(VMDisplayControl vMDisplay)
        {
            try
            {
                vMDisplay.Clear();
                vMDisplay.MVDRender.ClearImages();
                if (null == EdgePairFlawPattern.Result)
                {
                    return;
                }
                if (null != rTrainImage)
                {

                    vMDisplay.Image = rTrainImage;
                    //同步刷新，避免图形显示偏移
                    vMDisplay.MVDRender.Display(MVDRenderActivex.MVD_REFRESH_MODE.Sync);

                }
                else
                {
                    vMDisplay.MVDRender.Display();
                    // vMDisplay.Copy(TemplateWindow);
                }


            }


            finally
            {
                vMDisplay.MVDRender.Display();
            }
        }




        #endregion
        #region IDisposable Implementation
        public void Dispose()
        {
            // Dispose managed resources
            _StopWatch?.Stop();
            _StopWatch = null;
            LocalImage?.Dispose();
            TrainImage?.Dispose();
            LearnMatch?.Dispose();
            TemplateWindow?.Dispose();
            // Set large fields to null
            matchingViewModel = null;
            view = null;
            GC.SuppressFinalize(this);
        }
        #endregion
        /// 渲染轮廓点
        /// </summary>
        /// <param name="resEdgePointList"></param>
        public void DrawEdge(List<Tuple<MVD_POINT_F, Int32>> resEdgePointList)
        {
            try
            {
                var _SuccPointSetF = new CMvdPointSetF();
                var _ErrPointSetF = new CMvdPointSetF();
                foreach (var item in resEdgePointList)
                {
                    if (0 == item.Item2)
                    {
                        _SuccPointSetF.AddPoint(item.Item1.fX, item.Item1.fY);
                    }
                    else if (1 == item.Item2)
                    {
                        _ErrPointSetF.AddPoint(item.Item1.fX, item.Item1.fY);
                    }
                }

                if (0 != _SuccPointSetF.PointsList.Count)
                {
                    _SuccPointSetF.BorderColor = new MVD_COLOR(0, 255, 0, 255);
                    LearnMatch.AddShape(_SuccPointSetF);
                    _UIResPatternEdgeList.Add(_SuccPointSetF);
                }

                if (0 != _ErrPointSetF.PointsList.Count)
                {
                    _ErrPointSetF.BorderColor = new MVD_COLOR(255, 0, 0, 255);
                    LearnMatch.AddShape(_ErrPointSetF);
                    _UIResPatternEdgeList.Add(_ErrPointSetF);
                }
            }
            finally
            {
                LearnMatch.MVDRender.Display();
            }
        }



        //渲染卡尺
        public void DrawCaliper(List<CMvdRectangleF> resCaliperBoxList)
        {
            try
            {
                foreach (var item in resCaliperBoxList)
                {

                    var newItem = item.Clone() as CMvdRectangleF;
                    newItem.BorderColor = new MVD_COLOR(0, 0, 255, 255);
                    LearnMatch.AddShape(newItem);
                    _UIResPatternCaliperList.Add(newItem);

                }
            }
            finally
            {
                LearnMatch.MVDRender.Display();
            }
        }

        public void MVDRender_MVDShapeChangedEvent
    (
    MVDRenderActivex.MVD_SHAPE_EVENT_TYPE enEventType,
    MVD_SHAPE_TYPE enShapeType,
    CMvdShape cShapeObj
    )
        {
            if (MVDRenderActivex.MVD_SHAPE_EVENT_TYPE.MVD_SHAPE_SELECTED == enEventType)
            {
                return;
            }
            if (MVDRenderActivex.MVD_SHAPE_EVENT_TYPE.MVD_SHAPE_EDITED == enEventType)
            {
                return;
            }
            // 图形删除事件
            if (MVDRenderActivex.MVD_SHAPE_EVENT_TYPE.MVD_SHAPE_DELETED == enEventType)
            {
                foreach (var item in _UIPolylineSegmentList)
                {
                    if (cShapeObj == item)
                    {
                        _UIPolylineSegmentList.Remove(item);
                        break;
                    }
                }
                foreach (var item in _UIResPatternCaliperList)
                {
                    if (cShapeObj == item)
                    {
                        _UIResPatternCaliperList.Remove(item);
                        break;
                    }
                }

                foreach (var item in _UIResPatternEdgeList)
                {
                    if (cShapeObj == item)
                    {
                        _UIResPatternEdgeList.Remove(item);
                        break;
                    }
                }
            }
            if (MVDRenderActivex.MVD_SHAPE_EVENT_TYPE.MVD_SHAPE_ADDED == enEventType)
            {
                if (enShapeType == MVD_SHAPE_TYPE.MvdShapePolylineSegment)
                {
                    _UIPolylineSegmentList.Clear();
                    var polylineSegmentShape = cShapeObj as CMvdPolylineSegmentF;

                    _UIPolylineSegmentList.Add(polylineSegmentShape);

                }
            }


        }

    }
}
